#include "../pch.h"
#include "REFEncoding.h"
#include "REFBaseCodePageEncoding.h"

namespace BFX
{

//
// Constructors
//
REFBaseCodePageEncoding::REFBaseCodePageEncoding(int nPageCode, int nDataCodePage)
	: REFEncoding(nPageCode)
{
	m_pMemorySection	= NULL;
	m_pCodePage			= NULL;

	// Remember number of code page that we'll be using the table for.
	m_nDataTableCodePage	= nDataCodePage;
}

REFBaseCodePageEncoding::~REFBaseCodePageEncoding()
{
	// NOTE: Currently just allocate heap block
	// TODO: but we should use 'mmap' to create shared space.
	if (m_pMemorySection)
		delete[] m_pMemorySection;
}

//
// Overrides
//

//
// Methods
//

// Detect the memory section handle then re-initialize the memory section if necessary.
void REFBaseCodePageEncoding::CheckMemorySection() const
{
	if (m_pMemorySection == NULL)
	{
		REFBaseCodePageEncoding* pThis = const_cast<REFBaseCodePageEncoding*>(this);
		pThis->LoadCodePageTables();
	}
}

BYTE* REFBaseCodePageEncoding::GetSharedMemory(int iSize)
{
	// NOTE: Currently just allocate heap block
	// TODO: but we should use 'mmap' to create shared space. or store our codepage data in a named table.
	m_pMemorySection = new BYTE[iSize];
	memset(m_pMemorySection, 0, iSize);

	return m_pMemorySection;
}

// Get our code page byte count
int REFBaseCodePageEncoding::GetCodePageByteSize(int nCodePage)
{
	// Get our code page info
	const CodePageHeader* pCodePage = FindCodePage(nCodePage);

	// If NULL return 0
	if (pCodePage == NULL)
		return 0;

	BFX_ASSERT(pCodePage->ByteCount == 1 || pCodePage->ByteCount == 2);
	// Return what it says for byte count
	return pCodePage->ByteCount;
}

// We need to load tables for our code page
void REFBaseCodePageEncoding::LoadCodePageTables()
{
	const CodePageHeader* pCodePage = FindCodePage(m_nDataTableCodePage);

	// Make sure we have one
	BFX_ENSURE1 (pCodePage != NULL, "No data is available for current encoding.");

	// Remember our code page
	m_pCodePage = pCodePage;

	// We had it, so load it
	LoadManagedCodePage();
}

// Look up the code page pointer
const REFBaseCodePageEncoding::CodePageHeader* REFBaseCodePageEncoding::FindCodePage(int nCodePage)
{
	const CodePageDataFileHeader* pCodePageFileHeader = (const CodePageDataFileHeader*)s_pCodePagesData;
	// We'll have to loop through all of the pCodePageFileHeader[] items to find our code page, this isn't
	// binary or anything so its not monstrously fast.
	for (int i = 0; i < pCodePageFileHeader->CodePageCount; i++)
	{
		const CodePageIndex* pCodePageIndex = (&(pCodePageFileHeader->CodePages)) + i;

		if (pCodePageIndex->CodePage == nCodePage)
		{
			// Found it!
			const CodePageHeader* pCodePage =
				(CodePageHeader*)((BYTE*)pCodePageFileHeader + pCodePageIndex->Offset);
			return pCodePage;
		}
	}

	// Couldn't find it
	return NULL;
}

}	//	namespace BFX
